package web_frame

import "strings"

type treeNode struct {
	name     string
	children []*treeNode
	fullPath string
	isEnd    bool
}

// AddPath 用于将路径的各个部分插入到树中 [构建前缀树]
// put path: /user/get/:id
func (node *treeNode) AddPath(path string) {
	// 报错根节点，便于后续恢复
	root := node

	pathParts := strings.Split(path, "/")

	for idx, part := range pathParts {
		// 跳过路径的第一个空字符串（因为路径以 '/' 开头）
		if idx == 0 {
			continue
		}
		// 获取子节点
		children := node.children
		found := false
		// 检查当前路径部分是否已经存在于子节点中
		for _, child := range children {
			if child.name == part {
				found = true
				// 如果找到了匹配的节点，将当前节点指向该子节点
				node = child // 类深度优先
				break
			}
		}
		// 如果没有找到匹配的子节点，就创建一个新的子节点
		if !found {
			isEnd := false
			if idx == len(pathParts)-1 {
				isEnd = true
			}
			newChild := &treeNode{name: part, children: make([]*treeNode, 0), isEnd: isEnd}
			// 将新的节点添加到子节点列表中
			node.children = append(node.children, newChild)
			// 当前节点指向新添加的节点
			node = newChild
		}
	}
	// 恢复到树的根节点
	node = root
}

// Find 用于根据路径查找匹配的节点
// path: 表示待查找的路径，格式类似 "/user/get/1"
func (node *treeNode) Find(path string) *treeNode {
	// 将路径按 '/' 分割为多个部分
	pathParts := strings.Split(path, "/")
	fPath := ""

	// 遍历路径的每一部分
	for idx, part := range pathParts {
		// 跳过路径中的第一个空字符串（因为路径是以 '/' 开头）
		if idx == 0 {
			continue
		}

		// 获取当前节点的所有子节点
		// 判断路径当前节点内容是否已存在
		children := node.children

		// 在子节点中查找与当前路径部分匹配的节点
		for _, child := range children {
			// 匹配的条件：节点名称完全匹配、节点名称为 "*"，或者节点名称包含动态参数 ":"
			if child.name == part || child.name == "*" || strings.Contains(child.name, ":") {
				fPath += "/" + child.name
				child.fullPath = fPath
				node = child // 如果匹配成功，更新当前节点为匹配的子节点
				// 如果是路径的最后一部分，直接返回当前节点
				if idx == len(pathParts)-1 {
					return node
				}
				break
			}
		}
	}

	// 如果路径中的某一部分无法匹配，返回 nil
	return nil
}
